package com.jsg.sl651.server;

import com.jsg.sl651.boot.BootProperties;
import com.jsg.sl651.codec.FrameDecoder;
import com.jsg.sl651.codec.FrameEncoder;
import com.jsg.sl651.codec.impl.FrameDecoderImpl;
import com.jsg.sl651.codec.impl.FrameEncoderImpl;
import com.jsg.sl651.enhance.DefaultEnhanceHandler;
import com.jsg.sl651.enhance.EnhanceHandler;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.EventExecutorGroup;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;

import javax.validation.constraints.NotNull;
import java.util.Locale;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

@AllArgsConstructor
public class GroupConfig {
    private final BootProperties bootProperties;

    public static boolean isLinux() {
        String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT);
        return osName.contains("linux");
    }

    @Bean(name = "bossGroup")
    public EventLoopGroup bossGroup() {
        if (bootProperties.isLinuxUseEpoll() && isLinux()) {
            return new EpollEventLoopGroup(bootProperties.getBossThreadCount(), new NamedThreadFactory("bossGroup"));
        }
        return new NioEventLoopGroup(bootProperties.getBossThreadCount(),  new NamedThreadFactory("bossGroup"));
    }


    @Bean(name = "workerGroup")
    public EventLoopGroup workerGroup() {
        if (bootProperties.isLinuxUseEpoll() && isLinux()) {
            return new EpollEventLoopGroup(bootProperties.getWorkThreadCount(), new NamedThreadFactory("workerGroup"));
        }
        return new NioEventLoopGroup(bootProperties.getWorkThreadCount(), new NamedThreadFactory("workerGroup"));
    }


    @Bean(name = "businessGroup")
    public EventExecutorGroup businessGroup() {
        if (bootProperties.isLinuxUseEpoll() && isLinux()) {
            return new EpollEventLoopGroup(bootProperties.getBusinessThreadCount(), new NamedThreadFactory("businessGroup"));
        }
        return new NioEventLoopGroup(bootProperties.getBusinessThreadCount(), new NamedThreadFactory("businessGroup"));
    }

    @Bean(name = "frameEncoder")
    public FrameEncoder frameEncoder() {
        return new FrameEncoderImpl();
    }

    @Bean(name = "frameDecoder")
    public FrameDecoder frameDecoder() {
        return new FrameDecoderImpl(bootProperties.getMinFrameLength(), bootProperties.getMaxFrameLength(),bootProperties.getServerCodeType());
    }

    @Bean
    public EnhanceHandler enhanceHandler() {
        return new DefaultEnhanceHandler();
    }


    public static class NamedThreadFactory implements ThreadFactory {
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        public NamedThreadFactory(String name) {
//            SecurityManager s = System.getSecurityManager();
//            group = (s != null) ? s.getThreadGroup() :
//                    Thread.currentThread().getThreadGroup();
            group = Thread.currentThread().getThreadGroup();
            namePrefix = name +
                    "-t-";
        }

        @Override
        public Thread newThread(@NotNull Runnable r) {
            Thread t = new Thread(group, r,
                    namePrefix + threadNumber.getAndIncrement(),
                    0);
            if (t.isDaemon()) {
                t.setDaemon(false);
            }
            if (t.getPriority() != Thread.NORM_PRIORITY) {
                t.setPriority(Thread.NORM_PRIORITY);
            }
            return t;
        }
    }

}
